package cn.com.cym.gamezao.service.single.impl;

import cn.com.cym.gamezao.base.*;
import cn.com.cym.gamezao.entity.single.VaccineReg;
import cn.com.cym.gamezao.exception.BaseException;
import cn.com.cym.gamezao.repository.single.VaccineRegRepository;
import cn.com.cym.gamezao.service.single.VaccineRegService;
import cn.com.cym.gamezao.util.CommonUtils;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.lang.reflect.Field;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
@Transactional(rollbackFor = Exception.class)
public class VaccineRegImpl extends BaseImpl<VaccineReg> implements VaccineRegService {

    final VaccineRegRepository thisRepository;

    final EntityManager entityManager;

    public VaccineRegImpl(VaccineRegRepository vaccineRegRepository,EntityManager entityManager){
        this.thisRepository = vaccineRegRepository;
        this.entityManager = entityManager;
    }

    @Override
    public BaseRepository<VaccineReg, Long> getJpaRepository() {
        return thisRepository;
    }

    @Override
    public Page<VaccineReg> findByPageable(SearchPage searchPage) {
        String[] sortBy = searchPage.getSortBy().toArray(new String[searchPage.getSortBy().size()]);
        Pageable pageable = PageRequest.of(searchPage.getCurrent()-1, searchPage.getPageSize(), searchPage.getSort(), sortBy);
        Specification<VaccineReg> specification = new Specification<>() {
            private static final long serialVersionUID = -2661077778894635593L;
            @SneakyThrows
            @Override
            public Predicate toPredicate(Root<VaccineReg> root,CriteriaQuery<?> query, CriteriaBuilder cb) {
                final Map<String, Field> fieldMap = ReflectUtil.getFieldMap(VaccineReg.class);
                return cb.and(CommonUtils.pageSet(fieldMap,searchPage,cb,root));
            }
        };
        return this.thisRepository.findAll(specification, pageable);
    }

    @Override
    public synchronized VaccineReg apply(VaccineReg vaccineReg) {
        //判断是否存在相同项目已预约项目
        final List<VaccineReg> byCertificateCodeAndVaccine = this.thisRepository.getByCertificateCodeAndVaccine(vaccineReg.getCertificateCode(), vaccineReg.getVaccine());
        if(byCertificateCodeAndVaccine.size()>0 && byCertificateCodeAndVaccine.get(0).getNoticeDateTime()==null){
            throw new BaseException("已预约过相同项目", new ResultResponse("已预约过相同项目",502));
        }
        return this.save(vaccineReg);
    }

    @Override
    public List<VaccineReg> getAllBySearch(SearchPage searchPage) {
        // 分解查询语句

        String sql = " select * from s_vaccine_reg where 1=1 "+initCondition(searchPage);

        final List resultList = entityManager.createNativeQuery(sql,VaccineReg.class).getResultList();
        return resultList;
    }

    @Override
    public List<VaccineReg> getAllBySearchParams(String startDate, String endDate, String vaccine) {
        String sql = "select * from s_vaccine_reg where create_time>='"+startDate+"'  and create_time <= '"+endDate +"'";
        if(!"0".equals(vaccine)){
            sql+= " and vaccine ='"+vaccine+"'";
        }
        final List<VaccineReg> resultList = entityManager.createNativeQuery(sql,VaccineReg.class).getResultList();
        return resultList;
    }

    private String initCondition(SearchPage searchPage){

        StringBuffer sb=new StringBuffer();

        final List<ConditionItem> items = searchPage.getItems();

        for(ConditionItem item: items){
            if(CommonUtils.isEmpty(item.getValue())){
            }else if(item.getDateValue()!=null && !"".equals(item.getDateValue())){
                sb.append(" and ").append(initFieldName(item.getName()))
                        .append(item.getName().endsWith("1")? ">='" :"<='").append(item.getDateValue().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))).append("'");
            }else
            sb.append(" and ").append(initFieldName(item.getName())).append(item.getSign().equals("==")?"=":item.getSign()).append("'"+item.getValue()+"'");
        }
        //System.out.println(sb);
        return  sb.toString();
    }

    private String initFieldName(String fieldName){
        final String s = StrUtil.toUnderlineCase(fieldName);
        if(s.endsWith("1") || s.endsWith("2")){
            final String substring = s.substring(0, s.length() - 1);
            return substring;
        }
        return  s;
    }
}